#include <Windows.h>
#include <atltime.h>
#include "uti_consolecolor.h"
#include "uti_barseries.h"
using namespace std;
#pragma warning(disable : 4996)



BarSeries::BarSeries(BarSerInfo* pbarserinfo)
{
	memcpy(&m_serinfo, pbarserinfo, sizeof(m_serinfo));

	m_pmemman = new MemMan<BarData>(m_serinfo.sersize, m_serinfo.p);

	m_pmemman->InitUnitPointer(&m_pcur,&m_index);

	notfirstbar = false;

	//m_cmldaycnt = 0;
	//baccrossday = false;


	char* inst = m_serinfo.barinfo.instru;

	if ('I' == inst[0] && 'F' == inst[1])
		bCommidity = false;
	else
		bCommidity = true;
	
}

BarSeries::~BarSeries()
{
	if (NULL != m_pmemman)
	{
		delete m_pmemman;
	}
}

int BarSeries::TimeposCommodity(SYSTEMTIME& systm, SYSTEMTIME& startinter1, SYSTEMTIME& endinter1, SYSTEMTIME& startinter2, SYSTEMTIME& endinter2)
{
	CTime judgetm(systm);
	CTime starttm1(startinter1);
	CTime endtm1(endinter1);
	CTime starttm2(startinter2);
	CTime endtm2(endinter2);


	CTimeSpan startspan1= judgetm - starttm1;
	CTimeSpan endspan1 = judgetm - endtm1;
	CTimeSpan startspan2= judgetm - starttm2;
	CTimeSpan endspan2 = judgetm - endtm2;

	LONGLONG startspansec1 = startspan1.GetTotalSeconds();
	LONGLONG endspansec1 = endspan1.GetTotalSeconds();
	LONGLONG startspansec2 = startspan2.GetTotalSeconds();
	LONGLONG endspansec2 = endspan2.GetTotalSeconds();


	if (startspansec1 <= 0)
	{
		return 1;
	}
	else if (startspansec1 > 0 && endspansec1 < 0)
	{
		return 2;
	}
	else if (endspansec1 >= 0 && startspansec2 <= 0)
	{
		return 3;
	}
	else if (startspansec2 > 0 && endspansec2 < 0)
	{
		return 4;
	}
	else if (endspansec2 >= 0)
	{
		return 5;
	}


	return -1;
}

int BarSeries::TimeposStockindex(SYSTEMTIME& systm, SYSTEMTIME& startinter1, SYSTEMTIME& endinter1)
{
	CTime judgetm(systm);
	CTime starttm1(startinter1);
	CTime endtm1(endinter1);


	CTimeSpan startspan1= judgetm - starttm1;
	CTimeSpan endspan1 = judgetm - endtm1;


	LONGLONG startspansec1 = startspan1.GetTotalSeconds();
	LONGLONG endspansec1 = endspan1.GetTotalSeconds();


	if (startspansec1 <= 0)
	{
		return 1;
	}
	else if (startspansec1 > 0 && endspansec1 < 0)
	{
		return 2;
	}
	else if (startspansec1 >= 0 && endspansec1 >= 0)
	{
		return 3;
	}

	return -1;

}

LONGLONG BarSeries::GetCommodityBarspan(SYSTEMTIME& ticksys)//not used for tick type
{

	SYSTEMTIME inter_1_start, inter_1_end, inter_2_start, inter_2_end;
	memcpy(&inter_1_start, &ticksys, sizeof(SYSTEMTIME));
	memcpy(&inter_1_end, &ticksys, sizeof(SYSTEMTIME));
	memcpy(&inter_2_start, &ticksys, sizeof(SYSTEMTIME));
	memcpy(&inter_2_end, &ticksys, sizeof(SYSTEMTIME));
	inter_1_start.wHour = 10;
	inter_1_start.wMinute = 15;
	inter_1_start.wSecond = 0;
	inter_1_end.wHour = 10;
	inter_1_end.wMinute = 30;
	inter_1_end.wSecond = 0;
	inter_2_start.wHour = 11;
	inter_2_start.wMinute = 30;
	inter_2_start.wSecond = 0;
	inter_2_end.wHour = 13;
	inter_2_end.wMinute = 30;
	inter_2_end.wSecond = 0;



	int start_ret = TimeposCommodity(m_pcur->starttime, inter_1_start, inter_1_end, inter_2_start, inter_2_end);
	int tick_ret = TimeposCommodity(ticksys, inter_1_start, inter_1_end, inter_2_start, inter_2_end);
	/*if (-1 == start_ret || -1 == tick_ret)
	{
		SetConsoleColor(FOREGROUND_GREEN);  
		printf("[GetCommodityBarspan] start_ret:%d, tick_ret:%d\n", start_ret, tick_ret);
		SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);  
	}*/




	CTime tickctime(ticksys);
	CTime startctime(m_pcur->starttime);
	CTime inter_1_startctime(inter_1_start);
	CTime inter_1_endctime(inter_1_end);
	CTime inter_2_startctime(inter_2_start);
	CTime inter_2_endctime(inter_2_end);
	CTimeSpan retspan;

	if (tick_ret == start_ret)
		retspan = tickctime - startctime;
	else if (1 == start_ret && 3 == tick_ret)
	{
		CTimeSpan tmpspan1 = tickctime - inter_1_endctime;

		CTimeSpan tmpspan2 = inter_1_startctime - startctime;

		retspan = tmpspan1 + tmpspan2;
	}
	else if (1 == start_ret && 5 == tick_ret)
	{
		CTimeSpan tmpspan1 = tickctime - inter_2_endctime;

		CTimeSpan tmpspan2 = inter_2_startctime - inter_1_endctime;

		CTimeSpan tmpspan3 = inter_1_startctime - startctime;

		retspan = tmpspan1 + tmpspan2 + tmpspan3;
	}
	else if (3 == start_ret && 5 == tick_ret)
	{
		CTimeSpan tmpspan1 = tickctime - inter_2_endctime;

		CTimeSpan tmpspan2 = inter_2_startctime - startctime;

		retspan = tmpspan1 + tmpspan2;
	}
	else//avoid -1/2/4 value
	{
		SetConsoleColor(FOREGROUND_GREEN);  
		printf("[GetCommodityBarspan] start_ret:%d, tick_ret:%d\n", start_ret, tick_ret);
		SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);  
	}



	LONGLONG istartspan = 0;
	if (m_serinfo.barinfo.type == Bartype::sec)
		istartspan = retspan.GetTotalSeconds();
	else if (m_serinfo.barinfo.type == Bartype::min)
	{
		LONGLONG minspan = retspan.GetTotalMinutes();

		if (ticksys.wSecond < m_pcur->starttime.wSecond)
			istartspan = minspan + 1;
		else
			istartspan = minspan;

	}		
	//else if (m_serinfo.barinfo.type == Bartype::day)
	//	istartspan = retspan.GetDays();



	return istartspan;
}

LONGLONG BarSeries::GetStockindexBarspan(SYSTEMTIME& ticksys)//not used for tick type
{
	SYSTEMTIME inter_1_start, inter_1_end;
	memcpy(&inter_1_start, &ticksys, sizeof(SYSTEMTIME));
	memcpy(&inter_1_end, &ticksys, sizeof(SYSTEMTIME));
	inter_1_start.wHour = 11;
	inter_1_start.wMinute = 30;
	inter_1_start.wSecond = 0;
	inter_1_end.wHour = 13;
	inter_1_end.wMinute = 30;
	inter_1_end.wSecond = 0;




	int start_ret = TimeposStockindex(m_pcur->starttime, inter_1_start, inter_1_end);
	int tick_ret = TimeposStockindex(ticksys, inter_1_start, inter_1_end);

	CTime tickctime(ticksys);
	CTime startctime(m_pcur->starttime);
	CTime inter_1_startctime(inter_1_start);
	CTime inter_1_endctime(inter_1_end);
	CTimeSpan retspan;

	if (tick_ret == start_ret)
		retspan = tickctime - startctime;
	else if (1 == start_ret && 2 == tick_ret)
	{
		CTimeSpan tmpspan1 = tickctime - inter_1_endctime;

		CTimeSpan tmpspan2 = inter_1_startctime - startctime;

		retspan = tmpspan1 + tmpspan2;
	}
	else
	{
		SetConsoleColor(FOREGROUND_GREEN);  
		printf("[GetStockindexBarspan] start_ret:%d, tick_ret:%d\n", start_ret, tick_ret);
		SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);  
	}



	//get timespan related to bartype
	LONGLONG istartspan = 0;
	if (m_serinfo.barinfo.type == Bartype::sec)
		istartspan = retspan.GetTotalSeconds();
	else if (m_serinfo.barinfo.type == Bartype::min)
	{
		LONGLONG minspan = retspan.GetTotalMinutes();

		if (ticksys.wSecond < m_pcur->starttime.wSecond)
			istartspan = minspan + 1;
		else
			istartspan = minspan;

	}	
	//else if (m_serinfo.barinfo.type == Bartype::day)
	//	istartspan = retspan.GetDays();

	
	return istartspan;
}


LONGLONG BarSeries::GetBarspan(SYSTEMTIME& curstartsys)
{
	CTime barstart(m_pcur->starttime);
	CTime curstart(curstartsys);


	CTimeSpan span= curstart - barstart;
	LONGLONG ispansec = span.GetTotalSeconds();
	if (ispansec < 0)
	{
		pantheios::log_ALERT("[GetBarspan] ", m_serinfo.barinfo.instru, ", type:", panint(m_serinfo.barinfo.type), ", cnt:", panint(m_serinfo.barinfo.cnt));
		return LONGLONG(m_serinfo.barinfo.cnt);
	}

	//ispansec is >= 0, so ispanday must be >= 0;
	LONGLONG ispanday = span.GetDays();
	if ((curstartsys.wHour < m_pcur->starttime.wHour) ||
		(curstartsys.wHour == m_pcur->starttime.wHour && curstartsys.wMinute < m_pcur->starttime.wMinute) ||
		(curstartsys.wHour == m_pcur->starttime.wHour && curstartsys.wMinute == m_pcur->starttime.wMinute && curstartsys.wSecond < m_pcur->starttime.wSecond))
	{
		ispanday++;
	}


	if (m_serinfo.barinfo.type != Bartype::day)
	{
		if (ispanday > 0)
		{
			char startbuf[30] = {0};
			char curbuf[30] = {0};
			sprintf(startbuf, "%d:%d:%d:%d:%d:%d", m_pcur->starttime.wYear, m_pcur->starttime.wMonth, m_pcur->starttime.wDay, m_pcur->starttime.wHour, m_pcur->starttime.wMinute, m_pcur->starttime.wSecond);
			sprintf(curbuf, "%d:%d:%d:%d:%d:%d", curstartsys.wYear, curstartsys.wMonth, curstartsys.wDay, curstartsys.wHour, curstartsys.wMinute, curstartsys.wSecond);

			pantheios::log_NOTICE("[GetBarspan] ", m_serinfo.barinfo.instru, ", type:", panint(m_serinfo.barinfo.type), ", cnt:", panint(m_serinfo.barinfo.cnt),
				", barstart:", startbuf, ", curstart:", curbuf, ", ispanday:", panint(ispanday) );

			return LONGLONG(m_serinfo.barinfo.cnt);
		}
		else if (ispanday == 0)
		{
			if (true == bCommidity)
				return GetCommodityBarspan(curstartsys);//only deal with span (m_pcur->starttime and curstartsys in the same day)
			else
				return GetStockindexBarspan(curstartsys);//only deal with span (m_pcur->starttime and curstartsys in the same day)
		}
	}
	else
	{		

		return ispanday;
	}
	
}

void BarSeries::Addbardata(BarData* data)
{
	

	/*SYSTEMTIME ticksys;
	SetSystime(&ticksys, tick->TradingDay, tick->UpdateTime, tick->UpdateMillisec);*/

	if (notfirstbar == false)
	{		
		UpdateBar(data, true);
		notfirstbar = true;	
	}	
	else if ((m_serinfo.barinfo.type == Bartype::tick && m_pcur->tickcnt == m_serinfo.barinfo.cnt) ||
		(m_serinfo.barinfo.type != Bartype::tick && GetBarspan(data->starttime) >= m_serinfo.barinfo.cnt))
		//true == baccrossday)
	{
		m_pcur->isend = true;
		m_pmemman->NextUnitPointer(&m_pcur,&m_index);//get cur bar pointer and index
		UpdateBar(data, true);
		//if (true == baccrossday)
		//	baccrossday = false;
	}
	else
	{
		UpdateBar(data, false);
	}


}



void BarSeries::UpdateBar(BarData* data, bool updatestarttm)
{
	if (true == updatestarttm)
	{
		memcpy(&m_pcur->starttime, &data->starttime, sizeof(m_pcur->starttime));//used for write file record and bar complete judgement
		m_pcur->open = data->open;
		m_pcur->high = data->high;
		m_pcur->low = data->low;
		m_pcur->UpperLimitPrice = data->UpperLimitPrice;
		m_pcur->LowerLimitPrice = data->LowerLimitPrice;
		m_pcur->index = m_index;
	}		
	memcpy(&m_pcur->curtime, &data->curtime, sizeof(m_pcur->curtime));//used for write file record and bar complete judgement

	m_pcur->tickcnt += data->tickcnt;
	


	m_pcur->LastPrice = data->LastPrice;
	m_pcur->close = data->close;
	if (m_pcur->high < data->high)
		m_pcur->high = data->high;
	if (m_pcur->low > data->low) 
		m_pcur->low = data->low;
	m_pcur->AveragePrice = data->AveragePrice;
	m_pcur->vol += data->vol;
	m_pcur->Turnover += data->Turnover;
	m_pcur->OpenInterest = data->OpenInterest;
	m_pcur->OpenInterestDiff = data->OpenInterestDiff;


	strcpy(m_pcur->inst, data->inst);
	m_pcur->exch_open = data->exch_open;
	m_pcur->exch_close = data->exch_close;
	m_pcur->exch_high = data->exch_high;
	m_pcur->exch_low = data->exch_low;


	m_pcur->BidPrice1 = data->BidPrice1;
	m_pcur->BidVolume1 = data->BidVolume1;

	m_pcur->AskPrice1 = data->AskPrice1;
	m_pcur->AskVolume1 = data->AskVolume1;

}

//
//void BarSeries::Addbardata(BarData* data, int f)
//{
//	
//
//	/*SYSTEMTIME ticksys;
//	SetSystime(&ticksys, tick->TradingDay, tick->UpdateTime, tick->UpdateMillisec);*/
//
//	if (notfirstbar == false)
//	{		
//		UpdateBar(data, true, f);
//		notfirstbar = true;	
//	}	
//	else if ((m_serinfo.barinfo.type == Bartype::tick && m_pcur->tickcnt == m_serinfo.barinfo.cnt) ||
//		(m_serinfo.barinfo.type != Bartype::tick && GetBarspan(data->starttime) >= m_serinfo.barinfo.cnt) ||
//		true == baccrossday)
//	{
//		m_pcur->isend = true;
//		m_pmemman->NextUnitPointer(&m_pcur,&m_index);//get cur bar pointer and index
//		UpdateBar(data, true, f);
//		if (true == baccrossday)
//			baccrossday = false;
//	}
//	else
//	{
//		UpdateBar(data, false, f);
//	}
//
//
//}
//
//
//void BarSeries::UpdateBar(BarData* data, bool updatestarttm, int f)
//{
//	if (true == updatestarttm)
//	{
//		memcpy(&m_pcur->starttime, &data->starttime, sizeof(m_pcur->starttime));//used for write file record and bar complete judgement
//		m_pcur->open = data->open;
//		m_pcur->high = data->high;
//		m_pcur->low = data->low;
//		m_pcur->UpperLimitPrice = data->UpperLimitPrice;
//		m_pcur->LowerLimitPrice = data->LowerLimitPrice;
//	}		
//	memcpy(&m_pcur->curtime, &data->curtime, sizeof(m_pcur->curtime));//used for write file record and bar complete judgement
//
//	m_pcur->tickcnt += data->tickcnt;
//
//
//
//	m_pcur->LastPrice = data->LastPrice;
//	m_pcur->close = data->close;
//	if (m_pcur->high < data->high)
//		m_pcur->high = data->high;
//	if (m_pcur->low > data->low) 
//		m_pcur->low = data->low;
//	m_pcur->AveragePrice = data->AveragePrice;
//	m_pcur->vol += data->vol;
//	m_pcur->Turnover += data->Turnover;
//	m_pcur->OpenInterest = data->OpenInterest;
//	m_pcur->OpenInterestDiff = data->OpenInterestDiff;
//
//
//
//	m_pcur->BidPrice1 = data->BidPrice1;
//	m_pcur->BidVolume1 = data->BidVolume1;
//
//	m_pcur->BidPrice2 = data->BidPrice2;
//	m_pcur->BidVolume2 = data->BidVolume2;
//
//	m_pcur->BidPrice3 = data->BidPrice3;
//	m_pcur->BidVolume3 = data->BidVolume3;
//
//	m_pcur->BidPrice4 = data->BidPrice4;
//	m_pcur->BidVolume4 = data->BidVolume4;
//
//	m_pcur->BidPrice5 = data->BidPrice5;
//	m_pcur->BidVolume5 = data->BidVolume5;
//
//	m_pcur->AskPrice1 = data->AskPrice1;
//	m_pcur->AskVolume1 = data->AskVolume1;
//
//	m_pcur->AskPrice2 = data->AskPrice2;
//	m_pcur->AskVolume2 = data->AskVolume2;
//
//	m_pcur->AskPrice3 = data->AskPrice3;
//	m_pcur->AskVolume3 = data->AskVolume3;
//
//	m_pcur->AskPrice4 = data->AskPrice4;
//	m_pcur->AskVolume4 = data->AskVolume4;
//
//	m_pcur->AskPrice5 = data->AskPrice5;
//	m_pcur->AskVolume5 = data->AskVolume5;
//
//
//}
//
//void BarSeries::SetAccrossday()
//{
//	baccrossday = true;
//}
